package com.zzyl.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.DeviceDataPageReqDto;
import com.zzyl.mapper.DeviceDataMapper;
import com.zzyl.service.DeviceDataService;
import com.zzyl.vo.DeviceDataGraphVo;
import com.zzyl.vo.DeviceDataVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DeviceDataServiceImpl implements DeviceDataService {
    @Autowired
    private DeviceDataMapper deviceDataMapper;

    @Override
    public PageResponse<DeviceDataVo> queryDeviceDataPage(DeviceDataPageReqDto deviceDataPage) {
        PageHelper.startPage(deviceDataPage.getPageNum(), deviceDataPage.getPageSize());
        deviceDataPage.setStartDate(LocalDateTimeUtil.of(deviceDataPage.getStartTime()));
        deviceDataPage.setEndDate(LocalDateTimeUtil.of(deviceDataPage.getEndTime()));
        Page<DeviceDataVo> page = deviceDataMapper.selectByPage(deviceDataPage);
        return PageResponse.of(page, DeviceDataVo.class);
    }

    /**
     * 根据设备ID、功能ID和时间范围查询设备每日数据列表
     *
     * @param iotId 设备ID，用于标识特定的设备
     * @param functionId 功能ID，用于指定设备的特定功能或数据类型
     * @param startTime 开始时间，表示查询范围的起始时间
     * @param endTime 结束时间，表示查询范围的结束时间
     * @return 返回一个包含设备数据的列表，每个数据点代表一天的数据
     */
    @Override
    public List<DeviceDataGraphVo> queryDeviceDataListByDay(String iotId, String functionId, Long startTime, Long endTime) {
        // 将开始时间和结束时间转换为LocalDateTime对象，以便后续处理
        LocalDateTime startDate = LocalDateTimeUtil.of(startTime);
        LocalDateTime endDate = LocalDateTimeUtil.of(endTime);

        // 查询设备在指定日期范围内的每日数据列表
        List<DeviceDataGraphVo> list = deviceDataMapper.queryDeviceDataListByDay(iotId,functionId,startDate,endDate);

        // 将查询结果转换为一个映射，其中日期为键，数据值为值，以便快速查找特定日期的数据值
        Map<String, Double> map = list.stream().collect(Collectors.toMap(DeviceDataGraphVo::getDateTime, DeviceDataGraphVo::getDataValue));

        // 创建一个包含每天数据实例的列表，这些实例的日期从开始时间到结束时间
        List<DeviceDataGraphVo> deviceDataGraphVos = DeviceDataGraphVo.dayInstance(startDate);

        // 遍历每天的数据实例列表，如果映射中有对应日期的数据值，则设置该数据值
        deviceDataGraphVos.forEach(deviceDataGraphVo -> {
            Double dateValue = map.get(deviceDataGraphVo.getDateTime());
            if(dateValue != null){
                deviceDataGraphVo.setDataValue(dateValue);
            }
        });

        // 返回填充了数据值的设备数据列表
        return deviceDataGraphVos;
    }

    /**
     * 根据周查询设备数据列表
     *
     * @param iotId 设备的唯一标识符
     * @param functionId 设备功能的标识符
     * @param startTime 查询开始时间的长时间值
     * @param endTime 查询结束时间的长时间值
     * @return 返回一个包含设备数据的列表
     */
    @Override
    public Object queryDeviceDataListByWeek(String iotId, String functionId, Long startTime, Long endTime) {
        // 将开始时间和结束时间转换为LocalDateTime对象
        LocalDateTime startDate = LocalDateTimeUtil.of(startTime);
        LocalDateTime endDate = LocalDateTimeUtil.of(endTime);

        // 从数据库中查询指定设备和时间范围内的设备数据列表
        List<DeviceDataGraphVo> deviceDataGraphVoList = deviceDataMapper.queryDeviceDataListByWeek(iotId,functionId,startDate,endDate);

        // 将查询结果转换为一个映射，其中日期时间为键，数据值为值
        Map<String, Double> map = deviceDataGraphVoList.stream().collect(Collectors.toMap(DeviceDataGraphVo::getDateTime, DeviceDataGraphVo::getDataValue));

        // 创建一个包含每周数据的设备数据列表实例
        List<DeviceDataGraphVo> deviceDataGraphVos = DeviceDataGraphVo.weekInstance(startDate);

        // 遍历每周数据的设备数据列表，并根据映射设置相应的数据值
        deviceDataGraphVos.forEach(deviceDataGraphVo -> {
            Double dateValue = map.get(deviceDataGraphVo.getDateTime());
            if(dateValue != null){
                deviceDataGraphVo.setDataValue(dateValue);
            }
        });

        // 返回填充了数据的设备数据列表
        return deviceDataGraphVos;
    }
}
